package org.murillo.chufa.entry;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.murillo.chufa.entry.CacheEntry;

public class CacheEntryList<K, V> {

    private final CacheEntry<K, V>[] array;
    private volatile int currentsize;

    public CacheEntryList(int maxsize) {
        this.array = new CacheEntry[maxsize];
        this.currentsize = 0;
    }

    public int size() {
        return currentsize;
    }

    public boolean isEmpty() {
        return currentsize <= 0;
    }

    public boolean isFull() {
        return currentsize >= array.length;
    }

    public boolean contains(Object o) {
        for (int i = 0; i < currentsize; i++) {
            if (array[i] == o) {
                return true;
            }
        }
        return false;
    }

    public boolean add(CacheEntry<K, V> e) {
        if (e.getHard() == null) {
            throw new RuntimeException("HARD is null");
        }
        checkForRepeated(e);
        if (currentsize < array.length) {
            CacheEntry<K, V> old = array[currentsize];
            if (old != null) {
                synchronized (old) {
                    old.setHard(null);
                    array[currentsize] = e;
                }
            } else {
                array[currentsize] = e;
            }
            currentsize++;
            return true;
        }
        return false;
    }

    private void checkForRepeated(CacheEntry<K, V> e) {
        K key = e.getKey();
        for (int i = 0; i < array.length; i++) {
            if (array[i] != null && key.equals(array[i].getKey())) {
                if (i < currentsize) {
                    System.out.println(new RuntimeException("REPEATING KEYS IN HARD"));
                } else {
                    System.out.println(new RuntimeException("REPEATING KEYS IN HARD BORRADOS"));
                }
            }
        }
    }

    public CacheEntry<K, V> get(int i) {
        return array[i];
    }

    public CacheEntry<K, V> set(int i, CacheEntry<K, V> e) {
        if (e.getHard() == null) {
            throw new RuntimeException("HARD is null");
        }
        checkForRepeated(e);

        CacheEntry<K, V> c = array[i];
        synchronized (c) {
            c.setHard(null);
            //System.out.println("3 " + c);
            array[i] = e;
            return c;
        }
    }

    public int indexOf(CacheEntry<K, V> e) {
        for (int i = 0; i < currentsize; i++) {
            if (array[i] == e) {
                return i;
            }
        }
        return -1;
    }

    public int lastIndexOf(Object o) {
        for (int i = currentsize - 1; i >= 0; i--) {
            if (array[i] == o) {
                return i;
            }
        }
        return -1;
    }

    public CacheEntry<K, V>[] getArray() {
        return array;
    }

    public void freeLastN(int n) {
        currentsize = currentsize - n;
    }

    public void recycle(CacheEntry<K, V> rec) {
        int indexOf = -1;
        //System.out.println("B"+Thread.currentThread().getName()+" CurrentSize: "+hardlist.currentsize);
        for (int i = currentsize; i < array.length; i++) {
            if (array[i] == rec) {
                indexOf = i;
                break;
            }
        }
        //System.out.println("C"+Thread.currentThread().getName()+" CurrentSize: "+hardlist.currentsize);
        if (indexOf != currentsize) {
            CacheEntry<K, V> aux = array[currentsize];
            array[currentsize] = rec;
            array[indexOf] = aux;
        }
        currentsize++;
    }

    public int getCurrentsize() {
        return currentsize;
    }

    public void setCurrentsize(int currentsize) {
        this.currentsize = currentsize;
    }

    public void clear() {
        currentsize = 0;
        for (int i = 0; i < array.length; i++) {
            array[i] = null;
        }
    }
}
